package com.yupi.yuaiagent.agent;

import cn.hutool.core.util.StrUtil;
import com.yupi.yuaiagent.agent.model.AgentState;
import com.yupi.yuaiagent.dto.StepResult;
import com.yupi.yuaiagent.dto.ThoughtProcessStreamDTO;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Data
@Slf4j
public abstract class BaseAgent {

    // 核心属性
    private String name;

    // 提示词
    private String systemPrompt;
    private String nextStepPrompt;

    // 代理状态
    private AgentState state = AgentState.IDLE;

    // 执行步骤控制
    private int currentStep = 0;
    private int maxSteps = 10;

    // LLM 大模型
    private ChatClient chatClient;

    // Memory 记忆（需要自主维护会话上下文）
    private List<Message> messageList = new ArrayList<>();

    /**
     * 运行代理
     * @param userPrompt    用户提示词
     * @return
     */
    public String run(String userPrompt){
        if(this.state != AgentState.IDLE){
            throw new RuntimeException("Cannot run agent from state: " + this.state);
        } if (StrUtil.isBlank(userPrompt)) {
            throw new RuntimeException("Cannot run agent with empty user prompt");
        }
        // 2、执行，更改状态
        this.state = AgentState.RUNNING;
        // 记录消息上下文
        messageList.add(new UserMessage(userPrompt));
        // 保存结果列表
        List<String> results = new ArrayList<>();
        try {
            // 执行循环
            for (int i = 0; i < maxSteps && state != AgentState.FINISHED; i++) {
                int stepNumber = i + 1;
                currentStep = stepNumber;
                log.info("Executing step {}/{}", stepNumber, maxSteps);
                // 单步执行
                String stepResult = step();
                String result = "Step " + stepNumber + ": " + stepResult;
                results.add(result);
            }
            // 检查是否超出步骤限制
            if (currentStep >= maxSteps) {
                state = AgentState.FINISHED;
                results.add("Terminated: Reached max steps (" + maxSteps + ")");
            }
            return String.join("\n", results);
        } catch (Exception e) {
            state = AgentState.ERROR;
            log.error("error executing agent", e);
            return "执行错误" + e.getMessage();
        } finally {
            // 3、清理资源
            this.cleanup();
        }
    }

    /**
     * 运行代理（流式输出）
     *
     * @param userPrompt 用户提示词
     * @return 执行结果
     */
    public SseEmitter runStream(String userPrompt) {
        return runStreamWithThoughtProcess(userPrompt);
    }

    /**
     * 运行代理（带思考过程的流式输出）
     *
     * @param userPrompt 用户提示词
     * @return 执行结果
     */
    public SseEmitter runStreamWithThoughtProcess(String userPrompt) {
        // 创建一个超时时间较长的 SseEmitter
        SseEmitter sseEmitter = new SseEmitter(300000L); // 5 分钟超时
        // 使用线程异步处理，避免阻塞主线程
        CompletableFuture.runAsync(() -> {
            // 1、基础校验
            try {
                if (this.state != AgentState.IDLE) {
                    sendStreamMessage(sseEmitter, "错误：无法从状态运行代理：" + this.state, "content", 0, maxSteps);
                    sseEmitter.complete();
                    return;
                }
                if (StrUtil.isBlank(userPrompt)) {
                    sendStreamMessage(sseEmitter, "错误：不能使用空提示词运行代理", "content", 0, maxSteps);
                    sseEmitter.complete();
                    return;
                }
            } catch (Exception e) {
                sseEmitter.completeWithError(e);
            }
            // 2、执行，更改状态
            this.state = AgentState.RUNNING;
            // 记录消息上下文
            messageList.add(new UserMessage(userPrompt));
            // 保存结果列表
            List<String> results = new ArrayList<>();
            try {
                // 执行循环
                for (int i = 0; i < maxSteps && state != AgentState.FINISHED; i++) {
                    int stepNumber = i + 1;
                    currentStep = stepNumber;
                    log.info("Executing step {}/{}", stepNumber, maxSteps);

                    // 单步执行（带思考过程）
                    StepResult stepResult = stepWithThoughtProcess();

                    // 分块发送思考过程，实现真正的流式输出
                    if (stepResult.getThoughtProcess() != null && !stepResult.getThoughtProcess().isEmpty()) {
                        sendThoughtProcessInChunks(sseEmitter, stepResult.getThoughtProcess(), stepNumber, maxSteps);
                    }

                    // 收集主要内容（但不发送到前端）
                    if (stepResult.getMainContent() != null && !stepResult.getMainContent().isEmpty()) {
                        String result = "Step " + stepNumber + ": " + stepResult.getMainContent();
                        results.add(result);
                    }
                }

                // 检查是否超出步骤限制
                if (currentStep >= maxSteps) {
                    state = AgentState.FINISHED;
                    String terminateMsg = "Terminated: Reached max steps (" + maxSteps + ")";
                    results.add(terminateMsg);
                    // 发送任务完成提示（达到最大步骤）
                    sendStreamMessage(sseEmitter, "💡 **任务处理完成**\n\nAI智能体已达到最大处理步骤，任务处理完成。如果您需要继续或有其他问题，请随时告诉我！", "thinking", maxSteps, maxSteps);
                } else if (state == AgentState.FINISHED) {
                    // 发送任务完成提示（正常完成）
                    sendStreamMessage(sseEmitter, "✅ **任务已完成**\n\nAI智能体已成功完成您的任务！如果您有其他问题或需要进一步帮助，请随时告诉我。", "thinking", currentStep, maxSteps);
                }

                // 正常完成
                sseEmitter.complete();
            } catch (Exception e) {
                state = AgentState.ERROR;
                log.error("error executing agent", e);
                try {
                    sendStreamMessage(sseEmitter, "执行错误：" + e.getMessage(), "thinking", currentStep, maxSteps);
                    sseEmitter.complete();
                } catch (IOException ex) {
                    sseEmitter.completeWithError(ex);
                }
            } finally {
                // 3、清理资源
                this.cleanup();
            }
        });

        // 设置超时回调
        sseEmitter.onTimeout(() -> {
            this.state = AgentState.ERROR;
            this.cleanup();
            log.warn("SSE connection timeout");
        });
        // 设置完成回调
        sseEmitter.onCompletion(() -> {
            if (this.state == AgentState.RUNNING) {
                this.state = AgentState.FINISHED;
            }
            this.cleanup();
            log.info("SSE connection completed");
        });
        return sseEmitter;
    }

    /**
     * 发送流式消息
     */
    protected void sendStreamMessage(SseEmitter sseEmitter, String content, String type, int step, int totalSteps) throws IOException {
        ThoughtProcessStreamDTO dto = new ThoughtProcessStreamDTO(type, content, step, totalSteps, System.currentTimeMillis());
        String jsonMessage = convertToJson(dto);
        sseEmitter.send(jsonMessage);
    }

    /**
     * 转换为JSON格式
     */
    private String convertToJson(ThoughtProcessStreamDTO dto) {
        return String.format(
            "{\"type\":\"%s\",\"content\":\"%s\",\"step\":%d,\"totalSteps\":%d,\"timestamp\":%d}",
            dto.getType(),
            escapeJson(dto.getContent()),
            dto.getStep(),
            dto.getTotalSteps(),
            dto.getTimestamp()
        );
    }

    /**
     * 分块发送思考过程，实现流式输出
     */
    protected void sendThoughtProcessInChunks(SseEmitter sseEmitter, String thoughtProcess, int step, int totalSteps) throws IOException {
        if (thoughtProcess == null || thoughtProcess.isEmpty()) {
            return;
        }

        // 将思考内容按字符逐个输出，实现真正的字符级流式输出
        for (int i = 0; i < thoughtProcess.length(); i++) {
            char currentChar = thoughtProcess.charAt(i);

            // 发送当前字符
            sendStreamMessage(sseEmitter, String.valueOf(currentChar), "thinking", step, totalSteps);

            // 添加短暂延迟，模拟打字效果
            try {
                Thread.sleep(calculateCharDelay(currentChar));
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
    }

    /**
     * 根据字符类型计算延迟时间
     */
    private int calculateCharDelay(char currentChar) {
        // 基础延迟
        int baseDelay = 30;

        // 根据字符类型调整延迟
        if (currentChar == ' ' || currentChar == '\t') {
            // 空格和制表符更短的延迟
            return 10;
        } else if (currentChar == '\n') {
            // 换行符稍长的延迟
            return 50;
        } else if (String.valueOf(currentChar).matches("[。！？；，、：]")) {
            // 标点符号稍长延迟
            return 100;
        } else if (String.valueOf(currentChar).matches("[a-zA-Z0-9]")) {
            // 英文和数字标准延迟
            return 40;
        } else {
            // 中文字符标准延迟
            return 30;
        }
    }

    /**
     * 转义JSON特殊字符
     */
    private String escapeJson(String text) {
        if (text == null) {
            return "";
        }
        return text.replace("\\", "\\\\")
                  .replace("\"", "\\\"")
                  .replace("\r", "\\r")
                  .replace("\n", "\\n")
                  .replace("\t", "\\t");
    }

    public abstract String step();

    /**
     * 单步执行（带思考过程）
     * 默认实现，子类可以重写以提供更详细的思考过程
     */
    public StepResult stepWithThoughtProcess() {
        String result = step();
        return StepResult.full("正在执行步骤...\n" + result, result);
    }

    /**
     * 清理资源
     */
    protected void cleanup() {
        // 子类可以重写此方法来清理资源
    }
}